﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WestWorldRemake.Messaging;
using WestWorldRemake;
using WestWorldRemake.States;

namespace WestWorldRemake.Characters
{
    public enum MinionType { Lowly, Standard, Apostle, Creepy };

    public abstract class Minion : BaseGameEntity
    {
        protected int _HealthCurrent;
        protected int _HealthMax;
        protected double _Devoutness;
        protected int _NextDevoutness;
        protected bool _Following;
        protected LocationType _Location;
        protected int _Hunger;
        protected int _Fatigue;

        public Minion(string name, ConsoleColor color)
            : base(name, color)
        {
            _Hunger = 0;
            _Fatigue = 0;
            _Following = false;
        }
        public Minion(string name)
            : base(name)
        {
            _Hunger = 0;
            _Fatigue = 0;
            _Following = false;
        }

        public LocationType Location
        {
            get
            {
                return _Location;
            }
            set
            {
                _Location = value;
            }
        }
        public bool IsHungry()
        {
            return _Hunger > 28;
        }
        public bool IsTired()
        {
            return _Fatigue > 28;
        }
        public bool IsFollowing()
        {
            return _Following;
        }
        public bool CanLevelUp()
        {
            return _Devoutness > _NextDevoutness;
        }
        public Double Devoutness
        {
            get
            {
                return _Devoutness;
            }
        }
        public int NextDevoutNess
        {
            get
            {
                return _NextDevoutness;
            }
        }

        public void Eat()
        {
            _Hunger -= (new Random()).Next(10, 28);
        }
        public void Sleep()
        {
            _Fatigue -= (new Random()).Next(15, 28);
        }
        public virtual void IncreaseDevoutness(double scale)
        {
            //ever less than 0?
            double value = (28 - _Hunger) / 28.0 + (28 - _Fatigue) / 28.0;
            if ((new Random()).NextDouble() > .10)
                _Devoutness += value > 0 ? value*scale : 0;
        }
        public override void Update()
        {
            Random ran = new Random();
            if (ran.NextDouble() < .95)
                _Hunger++;
            if (ran.NextDouble() < .75)
                _Fatigue++;
        }
    }

    public class LowlyMinion : Minion
    {
        private StateMachine<LowlyMinion> _StateMachine;
        public StateMachine<LowlyMinion> StateMachine
        {
            get
            {
                return _StateMachine;
            }
        }

        public LowlyMinion(string name, LocationType location)
            : base(name, ConsoleColor.Cyan)
        {
            _HealthMax = 50;
            _NextDevoutness = 25;
            _Location = location;
            _StateMachine = new StateMachine<LowlyMinion>(this, States.LowlyMinionStates.LowlyMinionGlobalState.Instance, States.LowlyMinionStates.Worship.Instance);
        }

        public override Iffy HandleMessage(Telegram message)
        {
            return _StateMachine.HandleMessage(message);
        }
        public override void Update()
        {
            base.Update();
            _StateMachine.Update();
        }
        public override void IncreaseDevoutness(double scale)
        {
            base.IncreaseDevoutness(1.0);
        }
    }

    public class StandardMinion : Minion
    {
        private StateMachine<StandardMinion> _StateMachine;
        public StateMachine<StandardMinion> StateMachine
        {
            get
            {
                return _StateMachine;
            }
        }

        public StandardMinion(LowlyMinion minion, LocationType location)
            : base(minion.name, ConsoleColor.DarkCyan)
        {
            _HealthMax = 75;
            _Devoutness = minion.Devoutness - minion.NextDevoutNess;
            _NextDevoutness = 40;
            _Location = minion.Location;
            _StateMachine = new StateMachine<StandardMinion>(this, 
                StandardMinionStates.StandardMinionGlobalState.Instance, 
                StandardMinionStates.Worship.Instance);
        }

        public override Iffy HandleMessage(Telegram message)
        {
            return _StateMachine.HandleMessage(message);
        }

        public override void Update()
        {
            base.Update();
            _StateMachine.Update();
        }
        public override void IncreaseDevoutness(double scale)
        {
            base.IncreaseDevoutness(1.1);
        }
    }

    public class Apostle : Minion
    {
        private StateMachine<Apostle> _StateMachine;
        public StateMachine<Apostle> StateMachine
        {
            get
            {
                return _StateMachine;
            }
        }

        public Apostle(StandardMinion minion, LocationType location)
            : base(minion.name, ConsoleColor.Magenta)
        {
            _HealthMax = 125;
            _Devoutness = minion.Devoutness - minion.NextDevoutNess;
            _NextDevoutness = 75;
            _Location = minion.Location;
            _StateMachine = new StateMachine<Apostle>(this, ApostleStates.ApostleGlobalState.Instance, ApostleStates.Worship.Instance);
        }

        public override Iffy HandleMessage(Telegram message)
        {
            return _StateMachine.HandleMessage(message);
        }

        public override void Update()
        {
            base.Update();
            _StateMachine.Update();
        }
        public override void IncreaseDevoutness(double scale)
        {
            base.IncreaseDevoutness(1.3);
        }
    }

    public class Creepy : Minion
    {
        private StateMachine<Creepy> _StateMachine;
        public StateMachine<Creepy> StateMachine
        {
            get
            {
                return _StateMachine;
            }
        }

        public Creepy(Apostle minion, LocationType location)
            : base(minion.name, ConsoleColor.DarkMagenta)
        {
            _HealthMax = 200;
            _Devoutness = minion.Devoutness - minion.NextDevoutNess;
            _NextDevoutness = int.MaxValue;
            _Location = LocationType.Rlyeh;
            _StateMachine = new StateMachine<Creepy>(this, CreepyStates.CreepyGlobalState.Instance, CreepyStates.Worship.Instance);
        }

        public override Iffy HandleMessage(Telegram message)
        {
            return _StateMachine.HandleMessage(message);
        }

        public override void Update()
        {
            _StateMachine.Update();
        }
        public override void IncreaseDevoutness(double scale)
        {
            base.IncreaseDevoutness(2.0);
        }
    }
}
